//! `std::prelude` 模块的测试用例
//!
//! `std::prelude` 会自动导入到每个 Rust 程序的作用域中。
//! 本文件旨在测试一些预导入的最常用类型和 trait。

#[cfg(test)]
mod tests {
    // 虽然 prelude 是自动导入的，但为了清晰，我们可以在这里显式 `use`
    // use std::prelude::v1::*;

    /// 测试 `Option<T>`
    #[test]
    fn test_option() {
        let some_value: Option<i32> = Some(5);
        let no_value: Option<i32> = None;

        assert_eq!(some_value.unwrap(), 5);
        assert!(no_value.is_none());

        // `map` 方法
        assert_eq!(some_value.map(|x| x * 2), Some(10));
        assert_eq!(no_value.map(|x| x * 2), None);
    }

    /// 测试 `Result<T, E>`
    #[test]
    fn test_result() {
        let success: Result<i32, &str> = Ok(100);
        let failure: Result<i32, &str> = Err("Something went wrong");

        assert!(success.is_ok());
        assert!(failure.is_err());
        assert_eq!(success.unwrap_or(0), 100);
        assert_eq!(failure.unwrap_or(0), 0);
    }

    /// 测试 `String` 和 `&str`
    #[test]
    fn test_string() {
        let mut s = String::from("hello");
        s.push_str(", world");
        assert_eq!(s, "hello, world");

        let s_slice: &str = &s;
        assert!(s_slice.starts_with("hello"));
    }

    /// 测试 `Vec<T>`
    #[test]
    fn test_vec() {
        let v = vec![1, 2, 3];
        assert_eq!(v.len(), 3);
        assert_eq!(v[1], 2);
    }

    /// 测试 `Box<T>` (堆分配)
    #[test]
    fn test_box() {
        let b = Box::new(5);
        assert_eq!(*b, 5);
    }

    /// 测试 `Clone` 和 `Copy` trait
    #[test]
    fn test_clone_and_copy() {
        // `i32` 实现了 `Copy`，所以赋值是按位复制
        let x = 5;
        let y = x;
        assert_eq!(x, 5); // x 仍然可用

        // `String` 实现了 `Clone` 但没有实现 `Copy`
        let s1 = String::from("clone me");
        let s2 = s1.clone(); // 需要显式调用 `clone`
        // let s3 = s1; // 这会移动所有权，s1 将不可用

        assert_eq!(s1, s2);
    }

    /// 测试 `ToString` trait
    #[test]
    fn test_to_string() {
        let num = 42;
        let s = num.to_string();
        assert_eq!(s, "42");
    }

    /// 测试 `Drop` trait
    #[test]
    fn test_drop() {
        use std::sync::mpsc::{Sender, channel};

        struct Droppable {
            name: String,
            sender: Sender<String>,
        }

        impl Drop for Droppable {
            fn drop(&mut self) {
                // 当实例离开作用域时，会执行此代码
                println!("Dropping {}", self.name);
                self.sender.send(self.name.clone()).unwrap();
            }
        }

        let (tx, rx) = channel();
        {
            let _d1 = Droppable {
                name: "d1".to_string(),
                sender: tx.clone(),
            };
            let _d2 = Droppable {
                name: "d2".to_string(),
                sender: tx,
            };
            // d2 在 d1 之后声明，所以会先被 drop
        }

        // 验证 drop 的顺序
        assert_eq!(rx.recv().unwrap(), "d2");
        assert_eq!(rx.recv().unwrap(), "d1");
    }
}
